package git.soulbgm.proxy;

import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author 贺瑞杰
 * @version V1.0
 * @date 2019-04-08 15:42
 * @description
 */
public class JDKDynamicHandler<T> implements InvocationHandler {

    private T proxyTarget;

    /**
     * 装配被代理对象
     *
     * @param proxyTarget 被代理对象
     */
    public JDKDynamicHandler(T proxyTarget) {
        this.proxyTarget = proxyTarget;
    }

    /**
     * 返回代理对象的实例
     *
     * @return 代理对象的实例
     */
    public T newProxyInstance() {
        return (T) Proxy.newProxyInstance(proxyTarget.getClass().getClassLoader(), proxyTarget.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        addClassToDisk(proxy.getClass().getName(), proxyTarget.getClass(), "F:/$Proxy0.class");
        System.out.println("方法名称:" + method.getName());
        System.out.println("参数列表:" + args[0].getClass().getName());
        System.out.println("调用方法前...");
        Object object = method.invoke(proxyTarget, args);
        System.out.println("调用方法后...");
        return object;
    }

    /**
     * 用于生产代理对象的字节码，并将其保存到硬盘上
     * @param className
     * @param cl
     * @param path
     */
    private void addClassToDisk(String className, Class<?> cl, String path) {
        //用于生产代理对象的字节码
        byte[] classFile = ProxyGenerator.generateProxyClass(className, cl.getInterfaces());
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(path);
            //将代理对象的class字节码写到硬盘上
            out.write(classFile);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
